<template>
  <div class="com-form">
    <el-form :model="formView"
             :rules="rules"
             label-width="120px"
             ref="comForm"
             class="search-form">
      <template v-for="(query, index) in formItems">
        <template v-if="query.isBr">
          <br :key="`br-${index}`" />
        </template>
        <el-form-item :key="index"
                      :label="query.label"
                      :prop="query.prop"
                      :dataId="query.order"
                      class="form-item">

          <!--输入框-->
          <el-input v-if="query.type === SEARCH_TYPES.INPUT"
                    v-model="formView[query.prop]"
                    class="search-input-item"
                    :maxlength="query.max"
                    show-word-limit
                    @keyup.enter.native="handleFilter"
                    :placeholder="query.label"
                    clearable>
          </el-input>
          <!--数值输入框-->
          <el-input v-if="query.type === SEARCH_TYPES.NUMBER_INPUT"
                    type="number"
                    v-model="formView[query.prop]"
                    class="search-input-item"
                    @keyup.enter.native="handleFilter"
                    :suffix="query.unit"
                    :placeholder="query.label">
            <template slot="append">{{query.unit}}</template>
          </el-input>
          <!-- 文本域 -->
          <el-input v-if="query.type === SEARCH_TYPES.TEXTAREA"
                    class="search-input-item"
                    type="textarea"
                    :rows="2"
                    placeholder="请输入内容"
                    v-model="formView[query.prop]"
                    :maxlength="query.max"
                    show-word-limit>
          </el-input>

          <!--日期-年月日-->
          <el-date-picker v-if="query.type === SEARCH_TYPES.DATE"
                          class="search-input-item"
                          v-model="formView[query.prop]"
                          value-format="yyyy-MM-dd"
                          type="daterange"
                          :placeholder="query.label"
                          range-separator="至"
                          start-placeholder="开始时间"
                          end-placeholder="结束时间"
                          @change="changeCreateTime"
                          clearable>
          </el-date-picker>

          <!--下拉框-->
          <el-select v-if="query.type === SEARCH_TYPES.SELECT"
                     v-model="formView[query.prop]"
                     class="search-input-item"
                     @keyup.enter.native="handleFilter"
                     :placeholder="query.label"
                     clearable>
            <el-option v-for="item in query.selects || []"
                       :key="item.value"
                       :label="item.desc"
                       :value="item.value"></el-option>
          </el-select>

          <!-- 地址级联选择器 -->
          <el-cascader v-if="query.type === SEARCH_TYPES.CASCADER"
                       class="search-input-item"
                       v-model="formView[query.prop]"
                       :options="address"
                       @change="handleChangeAddr"></el-cascader>

          <!-- 身份证号码选择 -->
          <template v-if="query.type === SEARCH_TYPES.CARTDTYPE">
            <div class="search-input-item card-type">
              <el-select v-model="cardtype">
                <el-option v-for="item in cardType"
                           :key="item"
                           :label="item"
                           :value="item">{{item}}</el-option>
              </el-select>
              <el-input v-model="formView[query.prop]"
                        placeholder="请输入证件号" />
            </div>
          </template>

          <i v-if="!query.fixed"
             class="el-icon-delete form-icon"
             @click="handleDel(query)"></i>
          <i v-else
             class="el-icon-rank form-icon"
             style="opacity: 0"></i>
          <i class="el-icon-rank drag-handler form-icon"></i>
        </el-form-item>
      </template>
    </el-form>
    <slot name="headerOperate"></slot>
  </div>
</template>
<script lang='ts'>
import { Component, Prop, Vue, Watch, Emit } from 'vue-property-decorator'
import { area } from '@/api/formModule/area'
import { Form } from 'element-ui'
import Sortable from 'sortablejs'
interface formParams {
  createTime?: any[]
  startTime?: string
  endTime?: string
  [key: string]: any
}
const SEARCH_TYPES: object = {
  INPUT: 0,
  NUMBER_INPUT: 1,
  TEXTAREA: 2,
  DATE: 3,
  SELECT: 4,
  RADIO: 5,
  CHECKBOX: 6,
  CASCADER: 7,
  CARTDTYPE: 8
}

const cardType: string[] = ['身份证', '护照', '警官证', '驾驶证', '其他']
@Component({
  name: 'com-form'
})
export default class extends Vue {
  /**
   * 通过数组配置渲染form
   * @param [{
   *  prop 属性名称
   *  label 标签名
   *  type 元素类型，参考SEARCH_TYPES
   *  selects 当type=select时必须传入，为下拉框的具体值 [{value: '下拉框的key', desc: '展示的label'}]
   * }]
   */
  @Prop({ type: Array, required: true }) formItems!: any[]
  // @Prop({ type: Object, required: true }) rules!: any

  private rules: any = {}
  private SEARCH_TYPES: object = SEARCH_TYPES
  private cardType: string[] = cardType
  private cardtype = ''
  private newFormItem: any[] = []
  private order: string[] = []
  private formView: formParams = {}
  private address: any = area

  @Watch('formItems', { immediate: true, deep: true })
  private onFormItemsChanged (val: any[], oldVal: any[]) {
    if (val) {
      if (this.newFormItem.length !== 0) {
        // 如果是添加要素引起的，需要在原数组改变顺序的基础上添加新的要素进去
        const newArr = JSON.parse(JSON.stringify(val))
        const newOption = newArr.splice(-1, 1)[0]
        this.newFormItem.push(newOption)
      } else {
        this.newFormItem = JSON.parse(JSON.stringify(val))
      }
      val.map((elem) => {
        this.$set(this.formView, elem.prop, '')
        if (elem.selectProp) {
          this.$set(this.formView, elem.selectProp, '')
        }
      })
      this.setMust() // 设置必填标识
      this.$nextTick(() => {
        this.initDrag()
      })
    }
  }

  // 初始化
  initDrag () {
    const el = (this.$refs.comForm as Form).$el
    // let _that = this
    const sorttable = Sortable.create(el, {
      // group: "localStorage-example",
      animation: 150,
      sort: true,
      // dataIdAttr: 'dataId', // 根据dataId进行排序
      handle: '.drag-handler', // 配置了拖拽手柄意味着只能拖动这个手柄，拖其他的不行
      // ghostClass: 'blue-background-class',
      setData (dataTransfer) {
        // to avoid Firefox bug
        // Detail see : https://github.com/RubaXa/Sortable/issues/1012
        dataTransfer.setData('Text', '')
      },
      onEnd: ({ oldIndex, newIndex }) => {
        const targetRow = this.newFormItem.splice(oldIndex, 1)[0] // 被删除的项 ,会从原数组中删除此项
        this.newFormItem.splice(newIndex, 0, targetRow) // 把删除的项添加到新的位置
        this.handleonEnd(this.newFormItem)
      }
      // store: {
      //   get(sortable: any) {
      //     _that.order = localStorage.getItem(sortable.options.group.name);
      //     return _that.order ? _that.order.split('|') : [];
      //   },
      //   set(sortable: any) {
      //       _that.order = sortable.toArray();
      //       localStorage.setItem(sortable.options.group.name, _that.order.join('|'));
      //   }
      // }
    })
  }

  setMust () {
    this.formItems.forEach((item, index) => {
      if (item.isWrite === '1') {
        this.rules[item.prop] = [
          {
            required: true,
            message: '请补充完整',
            trigger: ['change', 'blur']
          }
        ]
      }
    })
    this.$forceUpdate()
  }

  clearValidate (): void {
    (this.$refs.comForm as Form).clearValidate()
  }

  @Emit('handleDel')
  handleDel (record: object) {
    return record
  }

  @Emit('handleonEnd')
  handleonEnd (newArr: any[]) {
    // 拖拽结束后改变item的序号order
    newArr.map((item, index) => {
      item.order = index + 1
    })
    return newArr
  }

  @Emit('getData')
  handleFilter () {
    let param = {}
    ;(this.$refs.comForm as Form).validate((valid) => {
      if (valid) {
        param = this.formView
      }
    })
    return param
  }

  @Emit('clear')
  clearFilter (): void {
    (this.$refs.comForm as Form).resetFields()
    this.clearValidate()
    for (const key in this.formView) {
      (this.formView as formParams)[key] = ''
      this.$set(this.formView, key, '')
    }
  }

  handleChangeAddr (value: any) {
    console.log(value)
  }

  changeCreateTime () {
    let start = (this.formView.createTime && this.formView.createTime[0]) || ''
    let end = (this.formView.createTime && this.formView.createTime[1]) || ''
    start = start ? `${start} 00:00:00` : start
    end = end ? `${end} 23:59:59` : end
    this.formView.startTime = start
    this.formView.endTime = end
  }
}
</script>
<style lang="scss">
.card-type {
  display: flex;
}
.search-form .el-form-item__content {
  display: flex !important;
  align-items: center !important;
}
.search-form .search-input-item {
  width: 400px !important;
  margin-right: 15px !important;
}
.drag-handler {
  margin-left: 15px;
}
.form-icon {
  font-size: 20px;
  cursor: pointer;
}
.form-date-picker {
  &.el-input__inner {
    position: relative;
    top: 1px;
    border-left: none;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
  }
}
.form-date-type {
  .el-input__inner {
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
  }
}

.new-row {
  display: block !important;
}
</style>
